perm filename TASTER.SAI[ALF,DEK]1 blob
sn#473388 filedate 1979-09-14 generic text, type T, neo UTF8
BEGIN "Taster"
COMMENT
The TASTER program provides a way to look at AlphaHOST output before it
actually gets spooled to the Alphatype, because AlphaSPOOL will be of only
limited intelligence, and AlphaTEX practically none. Obvious errors will
be detected and warnings will be issued for them.
One problem anticipated is that during various periods in the near
future, there will be times when only SAIL or only SCORE will be running.
In these events, it would be desirable to have versions of the program
tailored to each operating system. The changes would be minor and otherwise
the programs would be identical, and so the tailoring ought to be feasible.
Now we have some checks necessary to check cog traffic.
These are the crowding conditions:
h[i] >= g[i],
g[i] >= g[i-1],
h[i] >= h[i-1],
g[i] > h[i-2].
Traffic at c:
a) 1 if any chars entered or exited at c-1,
b) + 1 for each char entering at c,
c) + 1 for each char exiting at c.
If g[i]=c then b).
If h[i]=c-1 then c).
If g[i]=c-1 or h[i]=c-2 then a).
Traffic( n ) =
(g[n] enters here)
+ (g[n-1] enters here)
+ (h[n-1] exits) + (h[n-2] exits) + (h[n-3] exits)
+ (just DMA'd something).
= 1
- (g[n-1] = g[n])
- (h[n-1] = g[n]-1) - (h[n-2] = g[n]-1) - (h[n-3] = g[n]-1)
- (DMA = g[n]-1).
Note that although this formula looks like it yields values up to 6, the
fact that h[i] >= g[i] makes the two conditions (g[n-1] = g[n]) and
(h[n-1] = g[n]-1) mutually exclusive, and thus the maximum traffic we
can have is 5. We can also note that if g[n-1] does not equal g[n],
h[n-3] is at most g[n]-2 and will not contribute.
Now there is a slightly different problem we have to cover. That is
that although the cogs are still sent LR on RL-typeset lines, the traffic
conditions must be met RL. Here, we can just turn the conditions around,
g's "entering" and h's "exiting". The crowding conditions are:
h[i] >= g[i],
g[i] >= g[i-1],
h[i] >= h[i-1],
g[i] > h[i-2].
Traffic at c:
a) 1 if any chars entered or exited at c+1,
b) + 1 for each char entering at c,
c) + 1 for each char exiting at c.
If h[i]=c then b).
If g[i]=c+1 then c).
If g[i]=c+2 or h[i]=c+1 then a).
Traffic( n ) =
(h[n] enters here)
+ (h[n+1] enters here)
+ (g[n+1] exits) + (g[n+2] exits) + (g[n+3] exits)
+ (just DMA'd something)
= 1
- (h[n+1] = h[n])
- (g[n+1] = h[n]+1) - (g[n+2] = h[n]+1) - (g[n+3] = h[n]+1)
- (DMA = h[n]+1).
This of course means we cannot do h[n] when it happens, as we have to
wait until we get g[n+3]. Therefore, Traffic(n) could be the following
transformation:
1
- (h[n-2] = h[n-3])
- (g[n-2] = h[n-3]+1) - (g[n-1] = h[n-3]+1) - (g[n] = h[n-3]+1)
- (DMA = h[n-3]+1).
;
REQUIRE "{⎇{⎇" DELIMITERS;
DEFINE twenty = true;
DEFINE debug = false;
DEFINE simpel = { ifc not DEBUG thenc SIMPLE endc ⎇;
DEFINE verbose = false;
DEFINE ! = { comment ⎇;
DEFINE cr = { ('15 & null) ⎇;
DEFINE lf = { ('12 & null) ⎇;
DEFINE crlf = { ('15 & '12) ⎇;
DEFINE backlash = 36; ! CRS backlash compensation;
DEFINE mincog = 2048;
DEFINE maxcog = 3781;
DEFINE maxX = 55487;
DEFINE maxY = 29190;
DEFINE A!natural = 1365;
DEFINE B!flat = 2047;
INTEGER infile, ! Input file;
word, ! 1-word input buffer;
byte, ! Current input byte;
byte!pointer, ! Position in input buffer;
warnings, ! Number of non-fatal errors;
state, ! CRS line mode: LR, RL, blank;
A, ! Horizontal multiplier;
B, ! Vertical multiplier;
X, ! Horizontal position in dot units;
Y, ! Vertical position in feed units;
DMA, ! Last location a cog entered or left;
L, ! This line's left cog constraint;
R, ! This line's right cog constraint;
pos; ! Current position in cog ring;
INTEGER ARRAY lc,rc[0:3]; ! Most recent left and right cogs;
ifc TWENTY thenc
DEFINE eof = {!skip!⎇;
EXTERNAL INTEGER !skip!;
elsec
INTEGER count, brchar, eof, badfile;
endc
BOOLEAN eol, ! Have we just done an end-of-line command? ;
never!brite, ! At least one brightness command per spool;
brite!ok; ! Decides if legal to change brightness;
SIMPEL PROCEDURE Warning( STRING msg );
BEGIN "Warning"
warnings ← warnings + 1;
PRINT( (crlf&"WARNING: "), msg, crlf );
END "Warning";
SIMPEL PROCEDURE Cleanup;
BEGIN "Cleanup"
ifc TWENTY thenc CFILE( infile ); elsec RELEASE( infile ); endc
SetPrint( null, "T" );
END "Cleanup";
SIMPEL INTEGER PROCEDURE GetByte( STRING bad!spot(null) );
BEGIN "Getbyte"
INTEGER temp;
DO
BEGIN
IF byte!pointer = 0 THEN
BEGIN
word ← WORDIN( infile );
IF eof and bad!spot THEN
BEGIN "Fatal end of file"
PRINT( "
** FATAL ERROR ** Unexpected end of input; this is improper when scanning
", bad!spot, (crlf & "Processing was interrupted after "), warnings,
" cautionary messages.
" );
Cleanup;
USERERR( 0, 0, "UNEXPECTED END OF FILE", "X" )
END "Fatal end of file";
END;
byte!pointer ← (byte!pointer + 1) MOD 4;
END
UNTIL (temp ← (word ← word ROT 9) LAND '777) LAND '400 or eof;
RETURN( temp LAND '377 );
END "Getbyte";
SIMPEL INTEGER PROCEDURE GetWord( STRING where );
RETURN( GetByte("low-order byte of "&where&".")
+(GetByte("high-order byte of "&where&".") LSH 8) );
SIMPEL INTEGER PROCEDURE Cog( INTEGER x );
RETURN( x/32 + mincog );
SIMPEL PROCEDURE Adjust!Cogs;
BEGIN "Adjust cogs"
INTEGER d;
PRINT( "
Adjust cogs of previous character...
" );
eol ← false;
IF state = 0 THEN
Warning("Adjusting cogs not allowed when AlphaTEX is in blank state.");
d ← GetWord( "cog adjustment" );
lc[pos] ← lc[pos] + d;
rc[pos] ← rc[pos] + d;
ifc VERBOSE thenc
PRINT("This leaves cogs at [",lc[pos],",",rc[pos],"].",crlf);
endc
END "Adjust cogs";
SIMPEL PROCEDURE Display!Message;
BEGIN "Display message"
INTEGER i, len;
STRING mess;
mess ← null;
PRINT( "
Start a ", len ← byte, "-character message to the CRS display...
" );
IF len > 37 THEN
Warning("Alphatype cannot display a " &
CVS(len) & "-character message -- only 37 at most." );
FOR i ← 1 STEP 1 UNTIL len DO
BEGIN
byte ← GetByte
( "message for Alphatype display ("&CVS(Length(mess))&" characters):"&mess );
IF (" " LEQ byte LEQ "Z") or ("a" LEQ byte LEQ "z") THEN
mess ← mess & byte
ELSE
Warning( "Character '" & CVOS(byte) &
" not in AlphaType display range." )
END;
PRINT( "CRS Display (",Length(mess)," characters):",mess,crlf );
END "Display message";
SIMPEL PROCEDURE Begin!Page;
BEGIN "Start page"
INTEGER p;
PRINT( "
Begin page...
" );
state ← "LR";
IF not eol THEN
Warning(
"Without an end-of-line, some typesetting will be lost.");
L ← GetWord("new leftmost cog");
IF L < mincog or L > maxcog THEN
Warning( CVS(L)&" is an illegal left cog value." );
ARRCLR(lc,L);
ARRCLR(rc,L);
pos ← 0;
Y ← GetWord("new baseline coordinate");
IF Y > maxY THEN
Warning("Baseline coordinate " & CVS(Y)
& (" is too large. Should not exceed " & CVS(maxY) & ".") );
p ← GetWord("new page number");
IF p > 9999 THEN
Warning( CVS(p) & " is too large. Limited to 4 decimal digits." );
PRINT(
"Starting page ", p, ", down ", Y, " feed units, and over ", L, " cogs.
" );
END "Start page";
SIMPEL PROCEDURE End!of!Line;
BEGIN "End of line"
PRINT( "
End of line...
" );
eol ← true;
brite!ok ← true;
IF state = "LR" THEN
BEGIN
state ← "RL";
R ← GetWord("rightmost cog-setting");
L ← 0;
IF R-backlash < rc[pos] THEN
Warning("Right-cog limit should not be set to " & CVS(R) & "
because current rightcog + backlash compensation = " & CVS(rc[pos]+backlash) & ".")
ELSE IF R > maxcog+backlash THEN
Warning("Right-cog cannot be set to " & CVS(R) &
(" -- maximum possible value is " & CVS(maxcog+backlash)) );
ifc VERBOSE thenc
PRINT("New rightmost cog = ",R,crlf);
endc
END
ELSE
BEGIN
IF state NEQ "RL" THEN
Warning(
"Impossible to be at end of line while still in blank state.");
state ← "LR";
L ← GetWord("leftmost cog-setting");
IF L+rc[pos] > R THEN
Warning(
"Left-cog should not be set to " & CVS(L) & " because then the line goes to
" & CVS(L+rc[pos]-backlash) & ", past its right margin at "&CVS(R-backlash)&".");
ifc VERBOSE thenc
PRINT("New leftmost cog = ",L,crlf);
endc
END;
ARRCLR(lc,L);
ARRCLR(rc,L);
pos ← 0;
END "End of line";
SIMPEL PROCEDURE New!Character;
BEGIN "New character"
INTEGER i, m, n, ref!code;
PRINT( "
New character ", IF (" " < byte LEQ "Z") THEN (byte&null) ELSE ("'"&CVOS(byte)),
" being defined...
" );
m ← GetWord("new character starting address");
n ← GetWord("length of boundary data for new character");
FOR i ← 1 STEP 1 UNTIL n DO
byte ← GetByte
( "byte "&CVS(i)&" of "&CVS(n)&" bytes of boundary data for new character." );
PRINT( CVS(n) & (" bytes of boundary data successfully read in." & crlf) );
END "New character";
SIMPEL PROCEDURE Change!Multipliers;
BEGIN "Change multipliers"
PRINT( "
Change multipliers... " );
A ← GetWord("new horizontal multiplier");
IF A > 2047 THEN
Warning(CVS(A)&" is an illegal horizontal multiplier value;
multipliers must be < 2048.");
B ← GetWord("new vertical multiplier");
IF B > 2047 THEN
Warning(CVS(B)&" is an illegal vertical multiplier value;
multipliers must be < 2048.");
PRINT( "New multipliers are ", A, " and ", B, ".", crlf );
END "Change multipliers";
SIMPEL PROCEDURE Brightness!Control;
BEGIN "Change brightness"
INTEGER intensity;
PRINT( "
Brightness control...
" );
never!brite ← false;
IF not brite!ok THEN
Warning("Cannot change brightness in the middle of a line.");
intensity ← GetWord("new beam intensity");
IF intensity > 3000 or not intensity THEN
Warning(CVS(intensity)&" is an impossible beam intensity.");
PRINT( "Beam intensity now set to ", intensity, ".", crlf );
brite!ok ← false; ! Another change illegal until EOL;
END "Change brightness";
SIMPEL PROCEDURE End!of!Film;
BEGIN "End of film"
PRINT( "
End of film...
" );
IF not eol THEN
Warning(
"Without an end-of-line, everything you have typeset will be lost.");
PRINT(
"Now operator has changed film, Alphatype displays ON LINE and we continue...
" );
state ← 0;
END "End of film";
SIMPEL PROCEDURE Feed;
BEGIN "Feed"
INTEGER dy;
PRINT( "
Film-Feed...
" );
Y ← Y + (dy ← GetWord("feed value"));
IF dy < 2 THEN
Warning("Alphatype cannot feed only "&CVS(dy)&" units.")
ELSE IF Y > maxY THEN
Warning("Feeding "&CVS(dy)&" units puts the next baseline at "
& CVS(Y+dy) & (",
which is greater than " & CVS(maxY)) );
PRINT( "Baseline is now at ", Y, " feed units.", crlf );
END "Feed";
SIMPEL PROCEDURE Shuffle!Memory;
BEGIN
INTEGER m;
PRINT( "
Shuffle memory taking data from character ", byte, "...
" );
m ← GetWord("memory shuffle new-address");
END;
SIMPEL PROCEDURE Typeset;
BEGIN
INTEGER dl, dr, newpos;
IF eol THEN
BEGIN
eol ← false;
PRINT("
Typesetting:
");
END;
IF state = 0 THEN
Warning(
"Typesetting is not allowed when Alphatype is in blank state.");
IF " " LEQ byte LEQ "z" THEN
PRINT( byte&null )
ELSE
PRINT( "|", CVOS(byte) );
X ← GetWord("typeset horizontal coordinate");
dl ← GetByte("left cog-increment in typeset command.");
dr ← GetByte("right cog-increment in typeset command.");
newpos ← (pos+1) mod 4;
lc[newpos] ← lc[pos] + dl;
rc[newpos] ← rc[pos] + dr;
pos ← newpos;
IF lc[pos] > rc[pos] THEN
Warning(
"Left and right cogs have crossed. ["&CVS(lc[pos])&","&CVS(rc[pos])&"]");
ifc VERBOSE thenc
PRINT(crlf,"New cogs = [",lc[pos],",",rc[pos],"].",crlf);
endc
END;
SIMPEL PROCEDURE Initialize;
BEGIN
byte!pointer ← warnings ← state ← X ← Y ← pos ← L ← 0;
ARRCLR(lc);
ARRCLR(rc);
R ← maxcog;
A ← A!natural; B ← B!flat;
eol ← never!brite ← brite!ok ← true;
END;
ifc DEBUG thenc
EXTERNAL PROCEDURE Bail;
Bail;
endc
Initialize;
ifc TWENTY thenc
PRINT( "
What is the name of the file to be digested? " );
infile ← OPENFILE( null, "RC" );
elsec
OPEN(infile←GETCHAN,"DSK",8,2,0,count,brchar,eof);
DO BEGIN
PRINT( "
What is the name of the file to be digested? " );
LOOKUP( infile, INCHWL, badfile );
END
UNTIL not badfile;
endc
ifc DEBUG thenc
SetPrint( null, "B" );
elsec
SetPrint( null, "F" );
endc
WHILE true DO
BEGIN "Main loop"
byte ← GetByte;
IF eof THEN DONE "Main loop";
CASE byte OF
BEGIN
[0] CASE byte ← GetByte(
"incomplete command starting with 0, one of the following:
Adjust Cogs ( 0 & 0 & 0 )
Display Message ( 0 & 0 & length )
Begin Page ( 0 & 1 )
End of Line ( 0 & 2 )
New Character ( 0 & character code )" )
OF BEGIN
[0] IF 0 = byte ← GetByte(
"incomplete command starting with 0&0, one of the following:
Adjust Cogs ( 0 & 0 & 0)
Display Message ( 0 & 0 & length )" )
THEN Adjust!Cogs
ELSE Display!Message;
[1] Begin!Page;
[2] End!of!Line;
ELSE New!Character
END;
[1] Change!Multipliers;
[2] CASE byte ← GetByte(
"incomplete command starting with 2, one of the following:
Brightness Control ( 2 & 0 )
End of Film ( 2 & 1 )
Feed ( 2 & 2 )
Shuffle Memory ( 2 & character code )" )
OF BEGIN
[0] Brightness!Control;
[1] End!of!Film;
[2] Feed;
ELSE Shuffle!Memory
END;
ELSE Typeset
END;
END "Main loop";
SetPrint( null, "C" );
IF warnings THEN
PRINT( "
Nothing fatal detected, but ", warnings, " things tasted bad." )
ELSE
PRINT( "
Mmmmm . . . That tasted good!" );
Cleanup;
END "Taster"